﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Evolution
{
    abstract class Engine
    {        
        public Int16 Size;
        public byte[,] Matrix;
        public byte Percent1,Percent2;
        public TypeInfo Type1, Type2;
        Random rnd = new Random(DateTime.Now.Millisecond);

        public abstract void Setting();
        public abstract void PrintMatrix();
        
        /// <summary>
        /// Set random matrix.
        /// </summary>
        public void SetRandom()
        {
            Random rnd = new Random(DateTime.Now.Millisecond);
            //Border elements is empty (0).
            //0x0001 - 1st type of animal
            //0x0010 - 2nd type
            for (Int16 j = 0; j < Size; j++)
            {
                Matrix[0, j] = 0;
                Matrix[Size - 1, j] = 0;
            }
            for (Int16 i = 1; i < Size - 1; i++)
            {
                Matrix[i, 0] = 0;
                Matrix[i, Size - 1] = 0;
                for (Int16 j = 1; j < Size - 1; j++)
                {
                    byte RANDOM = (byte)rnd.Next(100);
                    if (RANDOM < Percent1)
                        Matrix[i, j] = 0x0001;
                    else
                        Matrix[i, j] = (byte)((100 - RANDOM < Percent2) ? 0x0010 : 0x0000);
                }
            }
        }


        protected Int32[] Positions = { -1,-1,   -1,0,   -1,1,   0,-1,   0,1,    1,-1,   1,0,    1,1 };
        /// <summary>
        /// New value of the one element.
        /// </summary>
        /// <param name="i">First index in matrix.</param>
        /// <param name="j">Second index in matrix.</param>
        /// <param name="Matrix"></param>
        /// <returns>New value of Matrix[i,j] value.</returns>
        public byte NewValue(Int16 i,Int16 j,ref byte[,] Matrix,ref byte[,] EatenArray)
        {
            byte CurrentElement=Matrix[i,j];
            byte Sum=0;
            for (byte k = 0; k < 15; k += 2)
                Sum += Matrix[i + Positions[k], j + Positions[k + 1]];
            byte Sum1 = (Byte)(Sum % 0x0010);
            byte Sum2 = (Byte)(Sum / 0x0010);
            if (CurrentElement==0x0001)
                { CurrentElement = Type1.Death(CurrentElement, Sum1); }
            else 
                if (CurrentElement==0x0010)
                    {
                        CurrentElement=Type2.Death(CurrentElement,Sum2);
                        if (Sum1 != 0)
                        {
                            byte k;
                            for (k = (byte)rnd.Next(8); Matrix[i + Positions[k*2], j + Positions[k*2 + 1]] != 0x0001; k = (byte)((k + 1) % 8)) ;
                            EatenArray[i + Positions[k], j + Positions[k + 1]] = 0;
                        }
                    }
                else
                    if (Sum1>=Type1.MinValueToBorn)
                    {
                        if (Sum2<Type2.MinValueToBorn)
                            {return 0x0001;}
                        else return (byte)(Sum1>Sum2 ? 0x0001:0x0010);                     
                    }
                    else
                        if (Sum2>=Type2.MinValueToBorn) return 0x0010;
            return CurrentElement;
        }


        /// <summary>
        /// Change all elements.
        /// </summary>
        public void GetNewMatrix()
        {
            byte[,] Buffer = new byte[Size, Size];
            byte[,] Eaten = new byte[Size, Size];
            for (Int16 i = 1; i < Size - 1; i++)
                for (Int16 j = 1; j < Size - 1; j++)
                    Eaten[i, j] = 1;
            Array.Copy(Matrix, Buffer, Size * Size);
            for (Int16 i = 1; i < Size - 1; i++)
                for (Int16 j = 1; j < Size - 1; j++)
                    Matrix[i, j] = NewValue(i, j, ref Buffer,ref Eaten);
            for (Int16 i = 1; i < Size - 1; i++)
                for (Int16 j = 1; j < Size - 1; j++)
                    Matrix[i, j] *= Eaten[i, j];
        }
        

    }
}
